/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package view;

import java.awt.*;
import java.awt.Graphics;
import java.util.ArrayList;
import javax.swing.*;
import org.w3c.dom.*;

/**
 * Cette classe hérite la classe JPanel qui dessine le graphe des liens des composantes.
 * @author NGUYEN Dac Cong Tai
 */
public class DrawingPane extends JPanel{
    private NodeList listLiens;
    private ArrayList<Point> listCoordonnees;
    private ArrayList listNomsConmposantes;
    private Image drawingImage;
    private Dimension ecran;
    private final double convDegGrad = 0.0174533;

    /**
     * Constructeur avec 3 paramètres
     * @param list la liste des noeuds des liens
     * @param listNoms la liste des noms des composantes
     * @param dim la dimension
     */
    public DrawingPane(NodeList list, ArrayList listNoms, Dimension dim) {
        super();
        setBackground(Color.white);
        this.listNomsConmposantes = listNoms;
        listLiens=list;
        ecran=new Dimension((dim.width-130)/3, (dim.height-150)/4);
        setPreferredSize(new Dimension(ecran.width, ecran.height));
    }

    /**
     * Renvoie le graphique.
     * @return le graphique
     */
    public Graphics getImageGraphics() {
        if (drawingImage == null) {
            reset();
        }
        return drawingImage.getGraphics();
    }

    /**
     * Réinitialise le graphique.
     */
    private void reset() {
        Dimension dim = getSize();
        drawingImage = this.createImage(dim.width, dim.height);
        Graphics g = drawingImage.getGraphics();
	g.setColor(Color.white);
	g.fillRect(0,0,dim.width, dim.height);
    }

    /**
     * Dessine le graphe sur le graphique
     * @param g le graphique
     */
    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        if (drawingImage == null) {
            reset();
        }
        g.drawImage(drawingImage, 0, 0, null);
        dessiner(g);
    }

    /**
     * Renvoie la liste des noms de composantes utilisées dans le graphe.
     * @param listLiens la liste des noeuds des liens
     * @return la liste des noms de composantes utilisées dans le graphe
     */
    private ArrayList getListComposantes(NodeList listLiens){
        ArrayList listNames = new ArrayList();
        for (int m=0; m<listLiens.getLength(); m++){
            //Recuperer le "liens"
            Element liens = (Element) listLiens.item(m);
            //Recuperer la liste des liens
            NodeList listDesLiens = liens.getElementsByTagName("lien");
            for (int n=0; n<listDesLiens.getLength(); n++){
                Element lien = (Element) listDesLiens.item(n);
                String de = lien.getAttribute("de").toString();
                if(!listNames.contains(de))
                    listNames.add(de);
                String vers = lien.getAttribute("vers").toString();
                if(!listNames.contains(vers))
                    listNames.add(vers);
            }
        }
        return listNames;
    }

    /**
     * Dessine une flèche à partir d'un point de départ jusqu'au point de destinataire sur le graphique.
     * @param g le graphique
     * @param depart le point de départ
     * @param destinataire le point de destinataire
     */
    private void dessinerFleche(Graphics g, Point depart, Point destinataire){
        Polygon arrow = new Polygon();
        int depX=0;
        int depY=0;
        int desX=0;
        int desY=0;

        if(depart.x>destinataire.x){
            depX=depart.x-7;
            desX=destinataire.x+7;
        } else {
            depX=depart.x+7;
            desX=destinataire.x-7;
        }
        if(depart.y>destinataire.y){
            depY=depart.y-7;
            desY=destinataire.y+7;
        } else {
            depY=depart.y+7;
            desY=destinataire.y-7;
        }
        arrow.addPoint(desX, desY);
        g.drawLine(depX, depY, desX, desY);

        if(depart.x==destinataire.x){
            //System.out.println("fleche...");
            if(depart.y>destinataire.y){
                g.drawLine(desX-2, desY+2, desX, desY);
                //g.drawLine(depart.x, depart.y-7, destinataire.x, destinataire.y+7);
                g.drawLine(desX+2, desY+2, desX, desY);
                /*arrow.addPoint(desX-3, desY+3);
                arrow.addPoint(desX+3, desY+3);*/
            } else{
                g.drawLine(desX-2, desY-2, desX, desY);
                //g.drawLine(depart.x, depart.y+7, destinataire.x, destinataire.y-7);
                g.drawLine(desX+2, desY-2, desX, desY);
                /*arrow.addPoint(desX-3, desY-3);
                arrow.addPoint(desX+3, desY-3);*/
            }
        } else if (depart.y == destinataire.y){
            if(depart.x>destinataire.x){
                g.drawLine(desX-3, desY+3, desX, desY);
                //g.drawLine(depart.x-7, depart.y, destinataire.x+7, destinataire.y);
                g.drawLine(desX+3, desY+3, desX, desY);
                /*arrow.addPoint(desX-3, desY+3);
                arrow.addPoint(desX+3, desY+3);*/
            } else{
                g.drawLine(desX-3, desY-3, desX, desY);
                //g.drawLine(depart.x+7, depart.y, destinataire.x-7, destinataire.y);
                g.drawLine(desX+3, desY-3, desX, desY);
                /*arrow.addPoint(desX-3, desY-3);
                arrow.addPoint(desX+3, desY-3);*/
            }
        } else {
            if(depart.x>destinataire.x){
                if (depart.y>destinataire.y){
                    g.drawLine(desX, desY+3, desX, desY);
                    //g.drawLine(depart.x-7, depart.y-7, destinataire.x+7, destinataire.y+7);
                    g.drawLine(desX+3, desY, desX, desY);
                    /*arrow.addPoint(desX, desY+3);
                    arrow.addPoint(desX+3, desY);*/
                } else{
                    g.drawLine(desX, desY-3, desX, desY);
                    //g.drawLine(depart.x-7, depart.y+7, destinataire.x+7, destinataire.y-7);
                    g.drawLine(desX+3, desY, desX, desY);
                    /*arrow.addPoint(desX, desY-3);
                    arrow.addPoint(desX+3, desY);*/
                }
            } else {
                if (depart.y>destinataire.y){
                    g.drawLine(desX-3, desY, desX, desY);
                    //g.drawLine(depart.x-7, depart.y-7, destinataire.x+7, destinataire.y+7);
                    g.drawLine(desX, desY+3, desX, desY);
                    /*arrow.addPoint(desX-3, desY);
                    arrow.addPoint(desX, desY+3);*/
                } else{
                    g.drawLine(desX-3, desY, desX, desY);
                    //g.drawLine(depart.x-7, depart.y+7, destinataire.x+7, destinataire.y-7);
                    g.drawLine(desX, desY-3, desX, desY);
                    /*arrow.addPoint(desX-3, desY);
                    arrow.addPoint(desX, desY-3);*/
                }
            }
        }
        //g.fillPolygon(arrow);
    }

    /**
     * Dessine le graphe sur le graphique.
     * @param g le graphique
     */
    public void dessiner(Graphics g) {
        //Dimension dim = new Dimension(0, 1);
        //System.out.println(this.getParent().getWidth());
        //double theta=convDegGrad*(120);
        ArrayList listNames = getListComposantes(listLiens);
        listCoordonnees = new ArrayList<Point>();
        int centreX=ecran.width/2;
        int centreY=ecran.height/2;
        //g.drawOval(centreX, centreY, 10, 10);

        for (int m=0;m<listNames.size();m++){
            int newX = (int) Math.round(centreX+listNames.size()*12*Math.cos(convDegGrad*(360/listNames.size()*m)));
            int newY = (int) Math.round(centreY+listNames.size()*12*Math.sin(convDegGrad*(360/listNames.size()*m)));
            listCoordonnees.add(new Point(newX+8, newY+8));
            g.setColor(Color.CYAN);
            g.fillOval(newX, newY, 16, 16);
            g.setColor(Color.black);
            String index = Integer.toString(listNomsConmposantes.indexOf(listNames.get(m))+1);
            g.drawString(index, newX+4, newY+12);
            //System.out.println("m="+m+": "+listNames.get(m)+", newX="+newX+" / newY="+newY);
            if(ecran.width<newX+10)
                ecran.width=newX+10;
            if(ecran.height<newY+12+index.length()*7)
                ecran.height=newY+12+index.length()*7;
        }

        for (int m=0; m<listLiens.getLength(); m++){
            //Recuperer le "liens"
            Element liens = (Element) listLiens.item(m);
            //Recuperer la liste des liens
            NodeList listDesLiens = liens.getElementsByTagName("lien");
            for (int n=0; n<listDesLiens.getLength(); n++){
                Element lien = (Element) listDesLiens.item(n);
                String de = lien.getAttribute("de").toString();
                String vers = lien.getAttribute("vers").toString();
                //String commentaire = lien.getAttribute("commentaire").toString();
                //g.setColor(decodeColor(n));
                dessinerFleche(g, listCoordonnees.get(listNames.indexOf(de)), listCoordonnees.get(listNames.indexOf(vers)));
            }
        }
        setPreferredSize(new Dimension(ecran.width,ecran.height));
    }

}
